import datetime
import hashlib
import os
import time
import traceback

import pandas as pd
import requests
from loguru import logger
import openpyxl
import json
import random
import numpy
import base64


class Xiao_Hong_Shu:
    def __init__(self, host, playwright, app_id):
        self.app_id = app_id
        self.playwright = playwright
        self.secret = "P4I8HCOP1OP7432XZVKR2MPJKKVQ7J"
        self.context = None
        self.browser = None
        self.page = None
        self.host = host
        self.post_url = self.host + "api/v1/storeAccount/getAccountList/redBook?type=订单销售,订单退款,货款明细,微信明细,订单结算明细,货款明细总数,微信明细总数,订单结算明细总数"
        self.index_url = "https://customer.xiaohongshu.com/login?service=https://ark.xiaohongshu.com/app-merchant/third-settle/account"
        self.tj_account = self.get_tujian_account()

    def login(self, account_obj: dict, login_type):
        '''
        登录
        :param account_obj: 登录账号信息
        :param login_type: 登录类型：1：登录账号，2：手机号码
        :return:
        '''
        browser = self.playwright.firefox.launch(headless=False)
        self.context = browser.new_context(accept_downloads=True)
        self.page = self.context.new_page()
        self.page.goto(self.index_url, timeout=60000)
        self.wait(self.page)
        time.sleep(5)
        if login_type == 1:
            logger.info("点击账号登录...")
            self.page.click('//div[text()="账号登录"]')
            logger.info("输入邮箱...")
            self.page.fill('input[name="email"]', account_obj['userName'])
            time.sleep(1)
            logger.info("输入密码...")
            self.page.fill('input[placeholder="密码"]', account_obj['pwd'])
            time.sleep(1)
        else:
            logger.info("输入手机号码...")
            self.page.fill('input[placeholder="手机号"]', account_obj['mobile'])
            time.sleep(1)
            logger.info("点击发送验证码...")
            self.page.query_selector('div:text-is("发送验证码")').click()
            self.check_rotate_code(account_obj['mobile'])
            self.check_qrcode(account_obj)
            self.check_sms_code(account_obj['mobile'])
        self.page.click('span.btn-content:has-text("登 录")')
        logger.info("点击登录...")
        time.sleep(15)
        # 判断是否需要选择店铺
        choice = False
        for k in range(10):
            try:
                if self.page.query_selector('div.seller-item') is not None:
                    choice = True
                    break
                time.sleep(1)
            except:
                pass
        time.sleep(1)
        if choice:
            self.page.query_selector(
                f'div.seller-item:has(div.seller-id:has-text("{account_obj["account"]}")) >> div.seller-login').click()
        for k in range(60):
            try:
                if self.page.query_selector('#searchInput') is not None:
                    break
                time.sleep(1)
                logger.info(f'等待页面加载【{k + 1}】秒')
            except:
                pass
        self.close_tips()

        # for k in range(60):
        #     try:
        #         if self.page.query_selector('button:has-text("返回旧版")') is not None:
        #             break
        #         time.sleep(1)
        #         logger.info(f'等待页面加载【{k + 1}】秒')
        #     except:
        #         pass
        # self.close_tips()
        # logger.info("返回旧版")
        # self.page.query_selector('button:has-text("返回旧版")').click()
        # time.sleep(1)
        # self.page.query_selector('div.d-checkbox:has-text("其他")').click()
        # time.sleep(1)
        # self.page.query_selector('div.d-popconfirm-footer >> button:has-text("确定")').click()
        time.sleep(5)
        logger.info('登录成功')

    def check_qrcode(self, account_obj):
        has_code = False
        for c in range(5):
            try:
                if self.page.query_selector('img.qrcode-img:visible') is not None:
                    has_code = True
                    break
            except:
                pass
            time.sleep(1)
        if has_code:
            self.page.go_back()
            # self.page.goto(self.index_url, timeout=60000)
            self.wait(self.page)
            time.sleep(5)
            logger.info("输入手机号码...")
            self.page.fill('input[placeholder="手机号"]', account_obj['mobile'])
            time.sleep(1)
            logger.info("点击发送验证码...")
            self.page.query_selector('div:text-is("发送验证码")').click()

    def check_rotate_code(self, mobile):
        has_code = False
        for c in range(5):
            try:
                if self.page.query_selector('#red-captcha-rotate:visible') is not None:
                    has_code = True
                    break
            except:
                pass
            time.sleep(1)
            logger.info(f'正在检查是否有旋转验证码【{c+1}】秒')
        if has_code:
            for k in range(20):
                try:
                    if self.page.query_selector('#red-captcha-rotate:visible') is None:
                        break
                    code_path = os.path.join(os.getcwd(), 'code.png')
                    self.page.query_selector('#red-captcha-rotate:visible').screenshot(path=code_path)
                    time.sleep(0.5)
                    dist = int(self.get_slider_xy(code_path))
                    box = self.page.query_selector('div.red-captcha-slider').bounding_box()
                    logger.info("重新滑动...")
                    track = self.get_tracks(dist + 15, 1, self.ease_out_quart)
                    ix = int(box['x'] + box['width'] // 2)
                    iy = int(box['y'] + box['height'] // 2)
                    self.page.mouse.move(ix, iy)
                    self.page.mouse.down(button='left')
                    self.move_to_gap(self.page, ix, iy, track)
                    time.sleep(1.5)
                    logger.info("滑动完成...")
                    time.sleep(5)
                except:
                    logger.info(traceback.format_exc())
                    # 如果是获取验证码结果失败，直接抛错重试
                    if '获取验证码结果失败' in traceback.format_exc():
                        raise Exception(traceback.format_exc())
            time.sleep(5)
            self.page.fill('input[placeholder="手机号"]', mobile)
            time.sleep(1)
            logger.info("点击发送验证码...")
            self.page.query_selector('div:text-is("发送验证码")').click()

    def ease_out_quart(self, x):
        return 1 - pow(1 - x, 4)

    def get_tracks(self, distance, seconds, ease_func):
        distance += 0
        tracks = [0]
        offsets = [0]
        for t in numpy.arange(0.0, seconds, 0.1):
            ease = ease_func
            offset = round(ease(t / seconds) * distance)
            tracks.append(offset - offsets[-1])
            offsets.append(offset)
        tracks.extend([-3, -2, -3, -2, -2, -2, -2, -1, -0, -1, -1, -1])
        return tracks

    def move_to_gap(self, page, ix, iy, track):
        """
        慢速移动鼠标
        :param ix:
        :param iy:
        :param track:
        :return:
        """
        f_y = [10, 12, 4, 6, 8, -4, -6, -8]
        mx = ix
        while track:
            x = track.pop(0)
            mx = mx + x
            page.mouse.move(mx, iy + random.choice(f_y))
            time.sleep(0.1)
        page.mouse.up()

    def get_slider_xy(self, code_path):
        api = 'http://api.ttshitu.com/base64'
        with open(code_path, 'rb') as f:
            base64_data = base64.b64encode(f.read())
            b642 = base64_data.decode()
        params = {"typeid": "29", "image": b642, "username": self.tj_account['tjName'],
                  "password": self.tj_account['tjPass']}
        headers = {'content-type': 'application/json;charset=UTF-8'}
        result = json.loads(requests.post(api, json=params, headers=headers).text)
        if result['success']:
            return result["data"]["result"].split(",")[0]
        else:
            raise Exception("获取验证码结果失败：【{}】".format(result['message']))

    def get_job_info(self, account_obj: dict):
        now = datetime.datetime.now().strftime("%Y-%m-%d")
        key = "{}:{}:{}:{}:{}:{}".format(account_obj['storeKey'], account_obj['storeId'], now, account_obj['userName'],
                                         account_obj['account'], account_obj['accountType'])
        url = self.host + "api/v1/storeAccount/getJobId/{}?appId={}&sign={}&timestamp={}"
        timestamp = int(time.time() * 1000)
        text = "{}{}{}".format(self.app_id, timestamp, self.secret)
        sign = hashlib.md5(text.encode(encoding='UTF-8')).hexdigest()
        res = requests.get(url.format(key, self.app_id, sign.upper(), timestamp))
        if res.status_code == 200:
            logger.info("获取到任务ID：【{}】".format(res.json()['data']))
            return res.json()['data'], key
        else:
            logger.info("获取任务ID失败：【{}】".format(res.json()))
            return None

    def upload_file(self, uri, coding_param, file_list):
        try:
            timestamp = int(time.time() * 1000)
            text = "{}{}{}".format(self.app_id, timestamp, self.secret)
            sign = hashlib.md5(text.encode(encoding='UTF-8')).hexdigest()
            logger.info("正在上传文件到服务器")
            url = self.host + uri + f"?appId={self.app_id}&sign={sign.upper()}&timestamp={timestamp}"
            files = []
            for file in file_list:
                files.append(('file', (open(file, 'rb'))))
            logger.info(f'上传文件到服务器url：{url}')
            response = requests.request("POST", url, files=files, headers={'codingParam': coding_param}, timeout=180)
            logger.info('上传文件到服务器结果：' + response.text)
        except:
            logger.info(traceback.format_exc())

    def encode_param(self, data_list):
        timestamp = int(time.time() * 1000)
        text = "{}{}{}".format(self.app_id, timestamp, self.secret)
        sign = hashlib.md5(text.encode(encoding='UTF-8')).hexdigest()
        url = self.host + f"api/v1/storeAccount/codingParams?appId={self.app_id}&sign={sign.upper()}&timestamp={timestamp}"
        res = requests.post(url, data=json.dumps(data_list), headers={'content-type': 'application/json'})
        if res.status_code == 200:
            return res.json()['data']

    def close_tips(self):
        for k in range(2):
            for t in range(3):
                try:
                    if self.page.query_selector('button:has-text("下次再说"):visible') is not None:
                        self.page.query_selector('button:has-text("下次再说"):visible').click(timeout=2000)
                    time.sleep(1)
                except:
                    pass
            for t in range(3):
                try:
                    if self.page.query_selector('button:has-text("下一步")') is not None:
                        self.page.query_selector('button:has-text("下一步")').click(timeout=2000)
                    time.sleep(1)
                except:
                    pass
            for c in range(2):
                for t in range(3):
                    try:
                        if self.page.query_selector('button:has-text("知道了")') is not None:
                            self.page.query_selector('button:has-text("知道了")').click(timeout=2000)
                            break
                        time.sleep(1)
                    except:
                        pass
            try:
                div = self.page.query_selector('a:has-text("一会儿再看"):visible')
                if div is not None:
                    try:
                        div.click(timeout=2000)
                        time.sleep(1)
                    except:
                        pass
                span = self.page.query_selector('//span[text()="知道了"]')
                if span is not None and span.is_visible():
                    try:
                        span.click(timeout=2000)
                        time.sleep(1)
                    except:
                        pass
            except:
                pass

    def get_tujian_account(self):
        url = self.host + "api/v1/tjAccount/findOne?appId={}&sign={}&timestamp={}"
        timestamp = int(time.time() * 1000)
        text = "{}{}{}".format(self.app_id, timestamp, self.secret)
        sign = hashlib.md5(text.encode(encoding='UTF-8')).hexdigest()
        res = requests.get(url.format(self.app_id, sign.upper(), timestamp))
        if res.status_code == 200:
            logger.info("获取到图鉴：【{}】".format(res.json()['data']))
            return res.json()['data']
        else:
            logger.info("获取图鉴失败：【{}】".format(res.json()))
            return None

    def get_login_account(self):
        try:
            timestamp = int(time.time() * 1000)
            text = "{}{}{}".format(self.app_id, timestamp, self.secret)
            sign = hashlib.md5(text.encode(encoding='UTF-8')).hexdigest()
            response = requests.get(
                self.post_url + "&appId={}&sign={}&timestamp={}".format(self.app_id, sign.upper(), timestamp))
            if response.status_code == 200:
                logger.info("获取小红书平台的账号密码信息成功")
                accounts = response.json()
                logger.info(accounts['data'])
                return accounts['data']
            else:
                logger.info("获取小红书平台的账号密码信息失败")
        except:
            traceback.format_exc()
        return []

    def wait(self, page, seconds=1):
        try:
            page.wait_for_load_state(state="domcontentloaded")
            time.sleep(seconds)
        except:
            traceback.format_exc()

    def close(self):
        try:
            if self.page:
                self.page.close()
        except:
            pass
        try:
            if self.browser:
                self.browser.close()
        except:
            pass
        try:
            if self.context:
                self.context.close()
        except:
            pass

    def check_sms_code(self, mobile):
        time.sleep(30)
        sms_text = self.get_sms_code(mobile)
        # 验证码格式示例：【小红书】您的验证码是：123456，....。
        if '小红书' not in sms_text:
            logger.info('获取验证码失败')
            raise Exception('获取验证码失败')
        sms_code = sms_text.split(':')[1].split('，')[0]
        self.page.query_selector('input[placeholder="验证码"]').fill(sms_code)
        time.sleep(1)

        # 获取手机验证码

    def get_sms_code(self, mobile):
        for t in range(3):
            try:
                res = requests.get(f'http://1.95.166.150:8997/api/v1/sms/info/{mobile}')
                logger.info(f'获取手机验证码结果：{res.text}')
                sms_text = res.json()['data']
                if sms_text is not None and '小红书' in sms_text:
                    return sms_text
                time.sleep(3)
            except:
                logger.info(traceback.format_exc())
        return ''

    def download_sale_detail(self, store, yesterday):
        logger.info("点击账户管理...")
        if self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理"):visible') is None:
            self.page.query_selector('span:text-is("资金")').click()
        time.sleep(1)
        self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理")').click(timeout=3000)
        time.sleep(5)
        self.close_tips()
        self.page.click('div.tab-name:has-text("货款资金")')
        time.sleep(5)
        logger.info("点击【店铺余额】...")
        self.page.click('div.d-tabs-pane > div > div > div:has-text("店铺余额")')
        time.sleep(1)
        logger.info('点击开始时间...')
        self.page.click('input[placeholder="开始时间"]')
        time.sleep(1)
        self.page.keyboard.press('Control+A')
        time.sleep(0.5)
        self.page.keyboard.press('Backspace')
        time.sleep(0.5)
        self.page.fill('input[placeholder="开始时间"]', yesterday)
        time.sleep(1)
        self.page.keyboard.press('Tab')
        time.sleep(1)
        self.page.click('div[data-selected="true"]')
        time.sleep(1)
        self.page.click('//div[text()="店铺余额"]')
        logger.info("点击查询...")
        with self.page.expect_response("*suez/finance/accountforweb/listAccountRecord") as response_info:
            self.page.click('//span[text()="查询"]')
        response_json = response_info.value.json()
        if response_json['data'] is not None and len(response_json['data']['list']) > 0:
            logger.info('点击导出...')
            try:
                with self.page.expect_download() as download_info:
                    self.page.click('//span[text()="导出"]')
                download_obj = download_info.value
            except:
                with self.page.expect_download() as download_info:
                    self.page.click('//span[text()="导出"]')
                download_obj = download_info.value
            file_dir = os.path.join(os.getcwd(), "temp")
            if not os.path.exists(file_dir):
                os.mkdir(file_dir)
            timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
            file_path = os.path.join(file_dir, "{}-{}-{}-{}.xlsx".format("小红书-结算账单-货款明细", store['platformStoreName'], yesterday.replace('-', ''), timestamp))
            if os.path.exists(file_path):
                os.remove(file_path)
            download_obj.save_as(file_path)
            # 等待文件下载完成
            for i in range(60):
                if os.path.exists(file_path):
                    break
                time.sleep(1)
            logger.info("文件已经下载：【{}】".format(file_path))
            return file_path
        else:
            logger.info("【货款金额-店铺余额】没有数据...")

    def get_sale_detail_count(self, period):
        logger.info("点击资金...")
        if self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理"):visible') is None:
            self.page.query_selector('span:text-is("资金")').click()
        time.sleep(1)
        self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理")').click(timeout=3000)
        time.sleep(5)
        self.close_tips()
        self.page.click('div.tab-name:has-text("货款资金")')
        time.sleep(5)
        logger.info("点击【店铺余额】...")
        self.page.click('div.d-tabs-pane > div > div > div:has-text("店铺余额")')
        time.sleep(1)
        logger.info('点击开始时间...')
        self.page.click('input[placeholder="开始时间"]')
        time.sleep(1)
        self.page.keyboard.press('Control+A')
        time.sleep(0.5)
        self.page.keyboard.press('Backspace')
        time.sleep(0.5)
        start_date = period + '-01'
        self.page.fill('input[placeholder="开始时间"]', start_date)
        time.sleep(1)
        self.page.keyboard.press('Tab')
        time.sleep(1)
        day_list = self.page.query_selector_all('div[data-calendar="body"]:has(div[data-selected="true"]) >> div.calendar-dayCell')
        last_day = None
        for day in day_list:
            if day.get_attribute('data-outside') is None:
                last_day = day
            elif day.get_attribute('data-outside') == 'true' and last_day is not None:
                break
        last_day.click()
        time.sleep(1)
        self.page.click('input[placeholder="资金流向"]')
        logger.info("点击查询...")
        with self.page.expect_response("*suez/finance/accountforweb/listAccountRecord") as response_info:
            self.page.click('//span[text()="查询"]')
        response_json = response_info.value.json()
        return response_json['data']['total']

    def download_wechat_detail(self, store, yesterday):
        logger.info("正在下载【货款金额-微信账户】...")
        if self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理"):visible') is None:
            self.page.query_selector('span:text-is("资金")').click()
        time.sleep(1)
        self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理")').click(timeout=3000)
        time.sleep(5)
        self.close_tips()
        self.page.click('div.tab-name:has-text("货款资金")')
        time.sleep(5)
        self.page.click('div.d-tabs-pane > div > div > div:has-text("微信账户")')
        time.sleep(5)
        logger.info('点击入账开始时间...')
        self.page.click('input[placeholder="入账开始时间"]')
        time.sleep(1)
        self.page.keyboard.press('Control+A')
        time.sleep(0.5)
        self.page.keyboard.press('Backspace')
        time.sleep(0.5)
        self.page.fill('input[placeholder="入账开始时间"]', yesterday)
        time.sleep(1)
        self.page.keyboard.press('Tab')
        time.sleep(1)
        self.page.click('div[data-selected="true"]')
        time.sleep(1)
        self.page.query_selector_all('//div[text()="微信账户"]')[-1].click()
        time.sleep(2)
        logger.info("点击搜索...")
        with self.page.expect_response("*suez/finance/accountforweb/queryStatementInRecords*") as response_info:
            self.page.click('//span[text()="搜索"]')
        response_json = response_info.value.json()
        if response_json['data'] is not None and len(response_json['data']['list']) > 0:
            logger.info("点击导出...")
            with self.page.expect_download() as download_info:
                self.page.click('//span[text()="导出"]')
            download_obj = download_info.value
            file_dir = os.path.join(os.getcwd(), "temp")
            if not os.path.exists(file_dir):
                os.mkdir(file_dir)
            timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
            file_path = os.path.join(file_dir, "{}-{}-{}-{}.xlsx".format("小红书-结算账单-微信明细", store['platformStoreName'], yesterday.replace('-', ''), timestamp))
            if os.path.exists(file_path):
                os.remove(file_path)
            download_obj.save_as(file_path)
            # 等待文件下载完成
            for i in range(60):
                if os.path.exists(file_path):
                    break
                time.sleep(1)
            logger.info("文件已经下载：【{}】".format(file_path))
            return file_path
        else:
            logger.info("【货款金额-微信账户】没有数据...")
            return None

    def get_wechat_detail_count(self, period):
        logger.info("正在下载【货款金额-微信账户】...")
        if self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理"):visible') is None:
            self.page.query_selector('span:text-is("资金")').click()
        time.sleep(1)
        self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理")').click(timeout=3000)
        time.sleep(5)
        self.close_tips()
        self.page.click('div.tab-name:has-text("货款资金")')
        time.sleep(5)
        self.page.click('div.d-tabs-pane > div > div > div:has-text("微信账户")')
        time.sleep(5)
        logger.info('点击入账开始时间...')
        self.page.click('input[placeholder="入账开始时间"]')
        time.sleep(1)
        self.page.keyboard.press('Control+A')
        time.sleep(0.5)
        self.page.keyboard.press('Backspace')
        time.sleep(0.5)
        start_date = period + '-01'
        self.page.fill('input[placeholder="入账开始时间"]', start_date)
        time.sleep(1)
        self.page.keyboard.press('Tab')
        time.sleep(1)
        day_list = self.page.query_selector_all('div[data-calendar="body"]:has(div[data-selected="true"]) >> div.calendar-dayCell')
        last_day = None
        for day in day_list:
            if day.get_attribute('data-outside') is None:
                last_day = day
            elif day.get_attribute('data-outside') == 'true' and last_day is not None:
                break
        last_day.click()
        time.sleep(1)
        self.page.query_selector_all('//div[text()="微信账户"]')[-1].click()
        time.sleep(2)
        logger.info("点击搜索...")
        with self.page.expect_response("*suez/finance/accountforweb/queryStatementInRecords*") as response_info:
            self.page.click('//span[text()="搜索"]')
        response_json = response_info.value.json()
        return response_json['data']['total']

    def download_bill_and_refund(self, store, last_month):
        logger.info("开始下载【结算账单的订单销售和订单退款】...")
        if self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理"):visible') is None:
            logger.info('点击资金')
            self.page.query_selector('span:text-is("资金")').click()
        time.sleep(1)
        try:
            self.page.query_selector('div.common-menu-wrap >> span:text-is("账单管理")').click(timeout=3000)
        except:
            pass
        for c in range(3):
            try:
                if self.page.query_selector('button:has-text("下次再说"):visible') is not None:
                    self.page.query_selector('button:has-text("下次再说"):visible').click()
                    break
            except:
                pass
            time.sleep(1)
        logger.info("点击结算帐单...")
        self.page.click('div.tab-name:has-text("结算账单")')
        self.wait(self.page)
        time.sleep(3)
        logger.info('点击【月度结算单】...')
        self.page.query_selector('div.tab-item:has-text("月度结算单")').click(timeout=3000)
        time.sleep(3)
        logger.info("点击搜索...")
        with self.page.expect_response('*suez/luna/ark/statement/queryList*') as response_info:
            self.page.click('span.btn-content:text-is("搜索")')
        response_json = response_info.value.json()
        data_list = response_json['data']['list']
        if len(data_list) > 0:
            bill_date = last_month
            index = 0
            has_bill = False
            for data in data_list:
                logger.info("检查是否是上个月的账单...")
                if str(data['statementPeriod']).startswith(bill_date):
                    logger.info("找到上个月的账单...")
                    has_bill = True
                    break
                index += 1
            if has_bill:
                logger.info("点击【下载账单】...")
                with self.page.expect_download() as download_info:
                    self.page.query_selector_all('span.btn-content:text-is("下载账单")')[index].click()
                download_obj = download_info.value
                file_dir = os.path.join(os.getcwd(), "temp")
                if not os.path.exists(file_dir):
                    os.mkdir(file_dir)
                timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
                file_path = os.path.join(file_dir, "{}-{}-{}-{}.xlsx".format("小红书-结算账单-订单销售-订单退款", store['platformStoreName'], last_month.replace('-', ''), timestamp))
                if os.path.exists(file_path):
                    os.remove(file_path)
                download_obj.save_as(file_path)
                # 等待文件下载完成
                for i in range(60):
                    if os.path.exists(file_path):
                        break
                    time.sleep(1)
                logger.info("文件已经下载：【{}】".format(file_path))
                return file_path
            return None
        else:
            logger.info("没有下载到账单...")
            return None

    def get_bill_and_refund_count(self, last_month):
        logger.info("开始下载【结算账单的订单销售和订单退款】...")
        if self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理"):visible') is None:
            logger.info('点击资金')
            self.page.query_selector('span:text-is("资金")').click()
        time.sleep(1)
        try:
            self.page.query_selector('div.common-menu-wrap >> span:text-is("账单管理")').click(timeout=3000)
        except:
            pass
        for c in range(3):
            try:
                if self.page.query_selector('button:has-text("下次再说"):visible') is not None:
                    self.page.query_selector('button:has-text("下次再说"):visible').click()
                    break
            except:
                pass
            time.sleep(1)
        logger.info("点击结算帐单...")
        self.page.click('div.tab-name:has-text("结算账单")')
        self.wait(self.page)
        time.sleep(3)
        logger.info('点击【月度结算单】...')
        self.page.query_selector('div.tab-item:has-text("月度结算单")').click(timeout=3000)
        time.sleep(3)
        logger.info("点击搜索...")
        with self.page.expect_response('*suez/luna/ark/statement/queryList*') as response_info:
            self.page.click('span.btn-content:text-is("搜索")')
        response_json = response_info.value.json()
        data_list = response_json['data']['list']
        filter_list = list(filter(lambda x: x['statementPeriod'].startswith(last_month), data_list))
        if len(filter_list) > 0:
            return filter_list[0]['commissionTotal']
        return 0

    def download_order_detail(self, store, yesterday):
        logger.info('下载【订单结算明细】...')
        if self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理"):visible') is None:
            logger.info("点击资金...")
            self.page.query_selector('span:text-is("资金")').click()
        time.sleep(1)
        self.page.query_selector('div.common-menu-wrap >> span:text-is("账单管理")').click(timeout=3000)
        time.sleep(5)
        self.close_tips()
        self.page.click('div.tab-name:has-text("订单结算明细")', timeout=3000)
        time.sleep(5)
        for count in range(3):
            try:
                if len(self.page.query_selector_all('span.btn-content:has-text("知道了")')) > 0:
                    self.page.query_selector('span.btn-content:has-text("知道了")').click()
                time.sleep(1)
            except:
                pass
        self.page.query_selector('input[placeholder="开始时间"]').click()
        self.page.query_selector_all('div:has(input[placeholder="开始时间"])')[-2].query_selector('div.slot-right').click(timeout=2000)
        self.page.fill('input[placeholder="开始时间"]', yesterday)
        self.page.keyboard.press("Tab")
        time.sleep(1)
        self.page.query_selector('div[data-selected="true"]').click()
        time.sleep(1)
        with self.page.expect_response('https://ark.xiaohongshu.com/api/suez/sellerstatementservice/ark/settle/order/page*') as res:
            self.page.query_selector('button:has-text("查询")').click()
        response = res.value
        if response.status == 200:
            if response.json()['data']['total'] == 0:
                logger.info('暂无数据')
                return None
        time.sleep(1)
        self.page.click('//span[text()="导出订单"]')
        time.sleep(1)
        self.page.click('span.btn-content:has-text("生成")')
        time.sleep(3)
        self.page.click('//span[text()="查看导出"]')
        logger.info("查看是否可以下载...")
        time.sleep(10)
        self.page.reload()
        self.wait(self.page)
        self.close_notice()
        # 找到“报表文件生成后将在系统中保留24小时，过期自动删除”的父div，在找到这个父div的下一层所有div（不含div里的div，只找下一层的div）
        div_count = len(self.page.query_selector_all('div >> div:has(div:text-is("报表文件生成后将在系统中保留24小时，过期自动删除"))'))
        div_list = self.page.query_selector(f'div >> div:has(div:text-is("报表文件生成后将在系统中保留24小时，过期自动删除")) >> nth={div_count - 1}').query_selector_all(' > div')
        next_day = (datetime.datetime.strptime(yesterday, '%Y-%m-%d') + datetime.timedelta(days=1)).strftime('%Y-%m-%d')
        for count in range(60):
            try:
                if len(self.page.query_selector_all('span.btn-content:has-text("下载")')) > 0:
                    break
                time.sleep(1)
            except:
                pass
        download_btn = None
        can_download = False
        for count in range(60):
            for div in div_list:
                row = div.query_selector(f'span:text-is("{yesterday} 00:00:00 - {next_day} 00:00:00")')
                if row is not None:
                    logger.info('找到下载的文件')
                    # 判断能否下载
                    download_btn = div.query_selector(f'span.btn-content:has-text("下载")')
                    if download_btn is not None:
                        logger.info('文件可以下载')
                        can_download = True
                        break
            if can_download:
                break
            logger.info('等待下载按钮出现')
            time.sleep(1)
        if download_btn is None and can_download:
            raise Exception('下载出错')
        time.sleep(2)
        with self.page.expect_download() as download_info:
            download_btn.click()
        download_obj = download_info.value
        file_dir = os.path.join(os.getcwd(), "temp")
        if not os.path.exists(file_dir):
            os.mkdir(file_dir)
        timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        file_path = os.path.join(file_dir, "{}-{}-{}-{}.xlsx".format("小红书-结算账单-订单结算明细", store['platformStoreName'], yesterday.replace('-', ''), timestamp))
        if os.path.exists(file_path):
            os.remove(file_path)
        download_obj.save_as(file_path)
        # 等待文件下载完成
        for count in range(60):
            if os.path.exists(file_path):
                break
            time.sleep(1)
        logger.info(f'下载文件【{file_path}】成功')
        if os.path.exists(file_path):
            # 先打开保存一次，否则pandas读取不到数据
            wb = openpyxl.load_workbook(file_path)
            wb.save(file_path)
            wb.close()
            logger.info("过滤昨天【{}】的数据".format(yesterday))
            order_detail_df = pd.read_excel(file_path, sheet_name="订单结算明细", header=0, dtype=str)
            logger.info("过滤列【结算时间】包含【{}】的数据...", yesterday)
            order_detail_df = order_detail_df[order_detail_df['结算时间'].str.contains(yesterday)]
            if len(order_detail_df) == 0:
                logger.info('暂无数据')
                return None
            logger.info("重新保存文件到【{}】".format(file_path))
            order_detail_df.to_excel(file_path, index=False)
            # 删除临时文件
            # os.remove(file_path)
            return file_path
        else:
            return None

    def get_order_detail_count(self, period):
        logger.info('下载【订单结算明细】...')
        if self.page.query_selector('div.common-menu-wrap >> span:text-is("账户管理"):visible') is None:
            logger.info("点击资金...")
            self.page.query_selector('span:text-is("资金")').click()
        time.sleep(1)
        self.page.query_selector('div.common-menu-wrap >> span:text-is("账单管理")').click(timeout=3000)
        time.sleep(5)
        self.close_tips()
        self.page.click('div.tab-name:has-text("订单结算明细")', timeout=3000)
        time.sleep(5)
        for count in range(3):
            try:
                if len(self.page.query_selector_all('span.btn-content:has-text("知道了")')) > 0:
                    self.page.query_selector('span.btn-content:has-text("知道了")').click()
                time.sleep(1)
            except:
                pass
        self.page.query_selector('input[placeholder="开始时间"]').click()
        self.page.query_selector_all('div:has(input[placeholder="开始时间"])')[-2].query_selector('div.slot-right').click(timeout=2000)
        start_date = period + '-01'
        self.page.fill('input[placeholder="开始时间"]', start_date)
        self.page.keyboard.press("Tab")
        time.sleep(1)
        day_list = self.page.query_selector_all('div[data-calendar="body"]:has(div[data-selected="true"]) >> div.calendar-dayCell')
        last_day = None
        for day in day_list:
            if day.get_attribute('data-outside') is None:
                last_day = day
            elif day.get_attribute('data-outside') == 'true' and last_day is not None:
                break
        last_day.click()
        time.sleep(1)
        with self.page.expect_response('https://ark.xiaohongshu.com/api/suez/sellerstatementservice/ark/settle/order/page*') as res:
            self.page.query_selector('button:has-text("查询")').click()
        response = res.value
        return response.json()['data']['total']

    def close_notice(self):
        for k in range(5):
            try:
                div = self.page.query_selector('a:has-text("一会儿再看"):visible')
                if div is not None:
                        div.click(timeout=2000)
                time.sleep(1)
            except:
                pass

    # 获取任务ID
    def get_job_id(self, key):
        timestamp = int(time.time() * 1000)
        text = "{}{}{}".format(self.app_id, timestamp, self.secret)
        sign = hashlib.md5(text.encode(encoding='UTF-8')).hexdigest()
        url = self.host + f"api/v1/storeAccount/getJobId/{key}?appId={self.app_id}&sign={sign.upper()}&timestamp={timestamp}"
        res = requests.get(url)
        logger.info(res.text)
        if res.status_code == 200:
            return res.json()['data']
